﻿#define Test

using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TextExtract
{
    public partial class Form1 : Form
    {
        enum Charset {
            SHIFT_JIS,
            GB2312,
            BIG5,
            UTF8
        }
        enum LangText
        {
            done,
            fail,
            add,
            del,
            app_title,
            lang_label,
            encode_label,
            src_path,
            dest_path,
            extract_btn,
            writeback_btn,
        }

        private string lang_file = "lang.csv";
        private string data_file = "data.xlsx";
        Dictionary<string, Dictionary<LangText, string>> lang_dict = new Dictionary<string, Dictionary<LangText, string>>();
        
        public Form1 () {
            InitializeComponent();
            LoadLang();
            InitLang();
            FilterList.Items.Add("*.cpp");
            FilterList.Items.Add("*.h");
            InitCharset(EncodeComb, Charset.UTF8);
        }

        private void LoadLang () {
            string path = Application.StartupPath + "/" + lang_file;
            if (!File.Exists(path)) return ;

            string data = File.ReadAllText(path);
            data = data.Replace("\r\n", "\n");
            string[] line = data.Split('\n');

            int i = 0, lang_cnt;
            string[] lang;
            for (; i < line.Length; i++) if (line[i].IndexOf(',') >= 0) break;      // find language line
            lang = line[i].Split(',');
            lang_cnt = lang.Length;

            for (i++; i < line.Length; i++) {
                string[] str = line[i].Split(',');
                if (str.Length < 2) continue;
                for (int j = 1; j < lang_cnt; j++) {
                    string language = lang[j];
                    LangText type = (LangText)Enum.Parse(typeof(LangText), str[0]);

                    Dictionary<LangText, string> dict;
                    if (!lang_dict.TryGetValue(language, out dict)) {
                        dict = new Dictionary<LangText, string>();
                        lang_dict.Add(language, dict);
                    }
                    dict.Add(type, str[j]);
                }
            }
        }

        private void SetupLang (string lang) {
            if (string.IsNullOrEmpty(lang)) return;
            Dictionary<LangText, string> dict;
            if (lang_dict.TryGetValue(lang, out dict)) {
                Text = dict[LangText.app_title];
                FilterAddBtn.Text = dict[LangText.add];
                FilterDelBtn.Text = dict[LangText.del];
                EncodeLab.Text = dict[LangText.encode_label];
                SrcpathLab.Text = dict[LangText.src_path];
                DestpathLab.Text = dict[LangText.dest_path];
                ExtractBtn.Text = dict[LangText.extract_btn];
                PushbackBtn.Text = dict[LangText.writeback_btn];
            }
        }
        private void InitLang () {
            string last = null;
            foreach (string lang in lang_dict.Keys) {
                Dictionary<LangText, string> dict;
                if (lang_dict.TryGetValue(lang, out dict)) {
                    LangComb.Items.Add(dict[LangText.lang_label]);
                }
                last = lang;
            }
            LangComb.SelectedIndex = LangComb.Items.Count - 1;
            SetupLang(last);
        }
        private void InitCharset (ComboBox comb, Charset def) {
            string[] name = Enum.GetNames(typeof(Charset));
            for (int i = 0; i < name.Length; i++) {
                comb.Items.Add(name[i]);
                if (string.Equals(name[i], def.ToString())) comb.SelectedIndex = i;
            }
        }

        private Encoding GetEncode (ComboBox comb) {
            Encoding encode = Encoding.UTF8;
            Charset en = (Charset)Enum.Parse(typeof(Charset), (string)comb.SelectedItem);
            switch (en) {
                case Charset.SHIFT_JIS: encode = Encoding.GetEncoding("shift-jis"); break;
                case Charset.GB2312: encode = Encoding.GetEncoding("gbk"); break;
                case Charset.BIG5: encode = Encoding.GetEncoding("big5"); break;
            }
            return encode;
        }

        private string GetCurrentLang() {
            int idx = LangComb.SelectedIndex;
            string cur = (string)LangComb.Items[idx];
            foreach (string lang in lang_dict.Keys) {
                Dictionary<LangText, string> dict;
                if (!lang_dict.TryGetValue(lang, out dict)) continue;
                if (string.Equals(cur, dict[LangText.lang_label])) return lang;
            }
            return null;
        }
        private void LangComb_SelectedIndexChanged (object sender, EventArgs e) {
            int idx = LangComb.SelectedIndex;
            string text = LangComb.Items[idx].ToString();
            foreach (string lang in lang_dict.Keys) {
                Dictionary<LangText, string> dict;
                if (lang_dict.TryGetValue(lang, out dict)) {
                    if (string.Equals(text, dict[LangText.lang_label])) SetupLang(lang);
                }
            }
        }

        private void SrcSelectBtn_Click (object sender, EventArgs e) {
            FolderBrowserDialog fd = new FolderBrowserDialog();
            fd.ShowNewFolderButton = true;
            fd.RootFolder = Environment.SpecialFolder.Desktop;
            if (fd.ShowDialog() == DialogResult.OK) {
                SrcpathBox.Text = fd.SelectedPath;
                SetDestpath(fd.SelectedPath);
            }
        }
        private void SetDestpath (string path) {
            if (string.IsNullOrEmpty(DestpathBox.Text)) {
                DestpathBox.Text = Application.StartupPath + "\\" + data_file;
            }
        }
        private void DestSelectBtn_Click (object sender, EventArgs e) {
            SaveFileDialog fd = new SaveFileDialog();
            fd.Filter = "All files (*.*)|*.*";
            fd.RestoreDirectory = true;
            if (fd.ShowDialog() == DialogResult.OK) DestpathBox.Text = fd.FileName;
        }
        private void ExtractBtn_Click (object sender, EventArgs e) {
            Encoding encode = GetEncode(EncodeComb);
            bool err = CharsetConv.ExtractFromDir(SrcpathBox.Text, DestpathBox.Text, GetFilters(), encode);
            string lang = GetCurrentLang();
            string message = err ? lang_dict[lang][LangText.fail] : lang_dict[lang][LangText.done];
            MessageBox.Show(message);
        }
        private void PushbackBtn_Click (object sender, EventArgs e) {
            Encoding encode = GetEncode(EncodeComb);
            bool err = CharsetConv.PushbackToDir(SrcpathBox.Text, DestpathBox.Text, encode, chkBox_AddAt.Checked);
            string lang = GetCurrentLang();
            string message = err ? lang_dict[lang][LangText.fail] : lang_dict[lang][LangText.done];
            MessageBox.Show(message);
        }

        private string[] GetFilters () {
            int count = FilterList.Items.Count;
            string[] arr = new string[count];
            for (int i = 0; i < count; i++) {
                arr[i] = FilterList.Items[i].ToString();
            }
            return arr;
        }
        private void FilterBox_KeyDown (object sender, KeyEventArgs e) {
            if (e.KeyCode == Keys.Enter) FilterAddBtn_Click(sender, e);
        }
        private void FilterAddBtn_Click (object sender, EventArgs e) {
            string text = FilterBox.Text;
            if (!string.IsNullOrEmpty(text)) {
                if (!text.StartsWith("*.")) text = "*." + text;
                FilterList.Items.Add(text);
                FilterBox.Text = null;
            }
        }
        private void FilterDelBtn_Click (object sender, EventArgs e) {
            int idx = FilterList.SelectedIndex;
            if (idx >= 0 && idx < FilterList.Items.Count) {
                FilterList.Items.RemoveAt(idx);
            }
        }
    }
}
